﻿<CodeSnippetTabbed DocLink="https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxTreeView#load-child-nodes-on-demand">
<CodeSnippetTabPage Text="Razor">@(@"<DxTreeView Data=""@DataSource""
            LoadChildNodesOnDemand=""true""
            HasChildrenExpression=""@(dataItem => ((DateTimeGroup)dataItem).HasSubGroups)""
            ChildrenExpression=""@(dataItem => ((DateTimeGroup)dataItem).GetSubGroups())""
            TextExpression=""@(dataItem => ((DateTimeGroup)dataItem).Title)"">
</DxTreeView>

@code {
    IEnumerable<DateTimeGroup> DataSource = new List<DateTimeGroup>() {
        new DateTimeGroup(new DateTime(DateTime.Now.Year, 1, 1), DateTimeGroupType.Year)
    };
}")
</CodeSnippetTabPage>
<CodeSnippetTabPage Text="DateTimeGroup" Language="csharp">@(@"public enum DateTimeGroupType { Year, Month, Day }

public class DateTimeGroup {
    public DateTimeGroup(DateTime dateTime, DateTimeGroupType groupType) {
        DateTime = dateTime;
        GroupType = groupType;
    }

    public DateTime DateTime { get; private set; }

    public DateTimeGroupType GroupType { get; private set; }

    public string Title {
        get {
            switch (GroupType) {
                case DateTimeGroupType.Year:
                    return DateTime.ToString(""yyyy"");
                case DateTimeGroupType.Month:
                    return DateTime.ToString(""MMMM"");
                case DateTimeGroupType.Week:
                    var culture = CultureInfo.CurrentCulture;
                    var weekNumber = culture.Calendar.GetWeekOfYear(DateTime,
                        culture.DateTimeFormat.CalendarWeekRule,
                        culture.DateTimeFormat.FirstDayOfWeek);
                    var weekStartDate = DateTimeUtils.CreateWeekStart(DateTime);
                    var weekEndDate = weekStartDate.AddDays(6);
                    var formatString = weekStartDate.Year == weekEndDate.Year ? ""MMMM d"" : ""MMMM d, yyyy"";
                    return String.Format(""Week {0} ({1} - {2})"", weekNumber,
                        weekStartDate.ToString(formatString), weekEndDate.ToString(formatString));
                case DateTimeGroupType.Day:
                    return DateTime.ToString(""dddd, MMMM d"");
                default:
                    return """";
            }
        }
    }

    public bool HasSubGroups => GroupType < DateTimeGroupType.Day;

    public IEnumerable<DateTimeGroup> GetSubGroups() {
        switch (GroupType) {
            case DateTimeGroupType.Year:
                return Enumerable.Range(1, 12)
                    .Select(m => new DateTimeGroup(new DateTime(DateTime.Year, m, 1), DateTimeGroupType.Month));
            case DateTimeGroupType.Month:
                var firstDayOfMonth = DateTime;
                var weekOffset = firstDayOfMonth.Month > 1 ? firstDayOfMonth.DayOfWeek - CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek : 0;
                var day = firstDayOfMonth.AddDays(-weekOffset);
                var nextMonthFirstDay = DateTime.AddMonths(1);
                var monthWeeks = new List<DateTimeGroup>();
                while (day < nextMonthFirstDay) {
                    monthWeeks.Add(new DateTimeGroup(day.Month == firstDayOfMonth.Month ? day : firstDayOfMonth, DateTimeGroupType.Week));
                    for (int i = 0; i < 7; i++)
                        day = day.AddDays(1);
                }
                return monthWeeks;
            case DateTimeGroupType.Week:
                var firstDayOfWeek = DateTimeUtils.CreateWeekStart(DateTime);
                var dayOfWeek = firstDayOfWeek;
                var weekDays = new List<DateTimeGroup>();
                for (int i = 0; i < 7; i++) {
                    if (dayOfWeek.Year == DateTime.Year && dayOfWeek.Month == DateTime.Month)
                        weekDays.Add(new DateTimeGroup(dayOfWeek, DateTimeGroupType.Day));
                    dayOfWeek = dayOfWeek.AddDays(1);
                }
                return weekDays;
            default:
                return null;
        }
    }
}")
</CodeSnippetTabPage>
</CodeSnippetTabbed>
